package com.bsj.power.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsj.power.common.config.exception.ApiException;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.config.global.TokenUser;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.constant.UserConstants;
import com.bsj.power.common.def.dto.PageDTO;
import com.bsj.power.common.def.entity.menu.Menu;
import com.bsj.power.common.def.entity.menu.RoleMenu;
import com.bsj.power.common.def.entity.role.Role;
import com.bsj.power.common.def.entity.role.UserRole;
import com.bsj.power.common.def.entity.user.User;
import com.bsj.power.common.def.entity.userOperateLog.UserOperateLog;
import com.bsj.power.common.def.vo.sys.RoleVO;
import com.bsj.power.common.def.vo.web.system.role.RoleAddVO;
import com.bsj.power.common.mapper.*;
import com.bsj.power.common.util.ParamCheckUtil;
import com.bsj.power.common.util.StpLoginUserUtil;
import com.bsj.power.system.service.MenuService;
import com.bsj.power.system.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yinhao
 * @version 1.0
 * @description 角色实现类
 * @date 2024/4/24
 */
@Slf4j
@Service
public class RoleServiceImpl implements RoleService {

    static final Map<Integer, String> roleTypeMap = Map.of(NumericalConstants.ONE, "系统管理员", NumericalConstants.TWO, "安全管理员",
            NumericalConstants.THREE, "安全审计员", NumericalConstants.FOUR, "业务操作员");

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private MenuService menuService;

    @Resource
    private UserOperateLogMapper userOperateLogMapper;

    /**
     * 新增/修改角色信息
     *
     * @param vo
     * @return
     */
    @Override
    @Transactional
    public Long addAndUpdate(RoleAddVO vo, String ip) {
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        Long parentId = tokenUser.getParentId();
//        Integer roleType = userRoleMapper.selectUserRoleType(loginUserId);
        if (parentId != -1) {            //不是系统超级管理员,无法操作
            throw new ApiException(JsonResultEnum.USER_IS_NOT_ADMIN_UN_OPERATE);
        }
        //接口权限校验
        List<Integer> menuIds = menuMapper.allMenuId();
        List<Integer> addMenuIds = vo.getMenuIds();
        if (!menuIds.containsAll(addMenuIds)) {
            throw new ApiException(JsonResultEnum.MENU_IS_NOT_EXIST);
        }
        addMenuIds = new HashSet<>(addMenuIds).stream().collect(Collectors.toList());
        Long roleId = vo.getRoleId();
        String roleName = vo.getRoleName();
        String roleSign = vo.getRoleSign();
        Integer roleType = vo.getRoleType();
        String roleTypeStr = roleTypeMap.get(roleType);
        if (StringUtils.isBlank(roleTypeStr)) {
            throw new ApiException(JsonResultEnum.ROLE_TYPE_NOT_EXIST);
        }
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        if (roleId != null) {
            if (roleMapper.exists(queryWrapper.lambda().eq(Role::getRoleSign, roleSign).ne(Role::getRoleId, roleId))) {
                throw new ApiException(JsonResultEnum.ROLE_SIGN_IS_EXIST);
            }
            if (roleMapper.exists(queryWrapper.lambda().eq(Role::getRoleName, roleName).ne(Role::getRoleId, roleId))) {
                throw new ApiException(JsonResultEnum.ROLE_NAME_IS_EXIST);
            }
        } else {
            if (roleMapper.exists(queryWrapper.lambda().eq(Role::getRoleSign, roleSign))) {
                throw new ApiException(JsonResultEnum.ROLE_SIGN_IS_EXIST);
            }
            if (roleMapper.exists(queryWrapper.lambda().eq(Role::getRoleName, roleName))) {
                throw new ApiException(JsonResultEnum.ROLE_NAME_IS_EXIST);
            }
        }
        Role addRole = new Role();
        BeanUtils.copyProperties(vo, addRole);
        if (roleId == null) {
            //新增
            roleMapper.insert(addRole);
            //添加角色与权限的关系
            batchInsertRoleMenu(addMenuIds, addRole.getRoleId());
//            String menuName = getMenuName(addMenuIds);
//            UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.ONE, NumericalConstants.TWO, ip, tokenUser);
//            setUserOperateContent(false, true, userOperateLog, roleName, null, roleTypeStr,
//                    null, roleSign, null, menuName, null);
//            userOperateLogMapper.insert(userOperateLog);
        } else {
            //默认角色不允许修改
            Role oldRole = roleMapper.selectById(roleId);
            ParamCheckUtil.isNull(oldRole, JsonResultEnum.ROLE_NOT_EXIST);
            if (oldRole.getIsDefault() != null) {
                throw new ApiException(JsonResultEnum.DEFAULT_ROLE_CANNOT_UPDATE_OR_DELETE);
            }
//            String menuName = getMenuName(addMenuIds);
//            String oldMenuName = null;
//            List<RoleMenu> roleMenus = roleMenuMapper.selectList(Wrappers.<RoleMenu>lambdaQuery().eq(RoleMenu::getRoleId, roleId));
//            if (!CollectionUtils.isEmpty(roleMenus)) {
//                List<Integer> oldMenuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
//                oldMenuName = getMenuName(oldMenuIds);
//            }
//            UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.TWO, NumericalConstants.TWO, ip, tokenUser);
//            setUserOperateContent(true, true, userOperateLog, roleName, oldRole.getRoleName(), roleTypeStr,
//                    roleTypeMap.get(oldRole.getRoleType()), roleSign, oldRole.getRoleSign(), menuName, oldMenuName);
            //更新
            roleMapper.updateById(addRole);
            //删除原先的关系
            roleMenuMapper.delete(Wrappers.<RoleMenu>lambdaQuery().eq(RoleMenu::getRoleId, roleId));
            //添加新的关系
            batchInsertRoleMenu(addMenuIds, roleId);
//            userOperateLogMapper.insert(userOperateLog);
        }
        return addRole.getRoleId();
    }

    /**
     * 获取权限名称集
     *
     * @param menuIds
     * @return java.lang.String
     * @author ljx
     * @time 2024/10/17 11:59
     */
    private String getMenuName(List<Integer> menuIds) {
        List<Menu> menus = menuMapper.selectList(Wrappers.<Menu>lambdaQuery().in(Menu::getMenuId, menuIds).select(Menu::getMenuName));
        if (!CollectionUtils.isEmpty(menus)) {
            return String.join(",", menus.stream().map(Menu::getMenuName).collect(Collectors.toList()));
        }
        return null;
    }


//    /**
//     * 设置操作内容
//     *
//     * @param isBefore       是否需要操作前内容
//     * @param isAfter        是否需要操作前内容
//     * @param userOperateLog
//     * @param roleName
//     * @param oldRoleName
//     * @param roleType
//     * @param oldRoleType
//     * @param roleSign
//     * @param oldRoleSign
//     * @param menu
//     * @param oldMenu
//     * @return void
//     * @author ljx
//     * @time 2024/10/17 11:29
//     */
//    private void setUserOperateContent(Boolean isBefore, Boolean isAfter, UserOperateLog userOperateLog, String roleName,
//                                       String oldRoleName, String roleType, String oldRoleType, String roleSign,
//                                       String oldRoleSign, String menu, String oldMenu) {
//        JSONObject jsonObject = new JSONObject();
//        if (isBefore) {
//            //操作前内容
//            jsonObject.put("roleName", oldRoleName);
//            jsonObject.put("roleType", oldRoleType);
//            jsonObject.put("roleSign", oldRoleSign);
//            jsonObject.put("menu", oldMenu);
//            userOperateLog.setContentBeforeOperate(jsonObject.toJSONString());
//        }
//        if (isAfter) {
//            //操作后内容
//            jsonObject.put("roleName", roleName);
//            jsonObject.put("roleType", roleType);
//            jsonObject.put("roleSign", roleSign);
//            jsonObject.put("menu", menu);
//            userOperateLog.setContentAfterOperate(jsonObject.toJSONString());
//        }
//    }

    /**
     * 批量添加角色与权限的关系
     *
     * @param menuIds
     * @param roleId
     * @return void
     * @author ljx
     * @time 2024/1/12 11:57
     */
    private void batchInsertRoleMenu(List<Integer> menuIds, Long roleId) {
        List<RoleMenu> roleMenus = menuIds.stream().map(menuId -> {
            RoleMenu roleMenuDO = new RoleMenu(roleId, menuId);
            return roleMenuDO;
        }).collect(Collectors.toList());
        roleMenuMapper.batchInsert(roleMenus);
    }

    /**
     * 删除角色
     *
     * @param roleId
     * @return
     */
    @Override
    public Integer delete(Long roleId, String ip) {
        ParamCheckUtil.isNull(roleId);
        Role role = roleMapper.selectById(roleId);
        ParamCheckUtil.isNull(role, JsonResultEnum.ROLE_NOT_EXIST);
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        Long loginUserId = tokenUser.getUserId();
        User user = userMapper.selectById(loginUserId);
        if (user.getParentId() != -1) {
            //不是系统超级管理员,无法操作
            throw new ApiException(JsonResultEnum.USER_IS_NOT_ADMIN_UN_OPERATE);
        }
        //默认角色不允许删除
        Role oldRole = roleMapper.selectById(roleId);
        ParamCheckUtil.isNull(oldRole, JsonResultEnum.ROLE_NOT_EXIST);
        if (oldRole.getIsDefault() != null) {
            throw new ApiException(JsonResultEnum.DEFAULT_ROLE_CANNOT_UPDATE_OR_DELETE);
        }
        Long count = userRoleMapper.selectCount(new QueryWrapper<UserRole>().lambda().eq(UserRole::getRoleId, roleId));
        if (count > 0) {
            throw new ApiException(JsonResultEnum.ROLE_NOT_DELETE);
        }
        int delete = roleMapper.deleteById(roleId);
        if (delete > 0) {
//            String oldMenuName = null;
//            List<RoleMenu> roleMenus = roleMenuMapper.selectList(Wrappers.<RoleMenu>lambdaQuery().eq(RoleMenu::getRoleId, roleId));
//            if (!CollectionUtils.isEmpty(roleMenus)) {
//                List<Integer> oldMenuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
//                oldMenuName = getMenuName(oldMenuIds);
//            }
            //删除角色与权限的关系
            roleMenuMapper.delete(new QueryWrapper<RoleMenu>().lambda().eq(RoleMenu::getRoleId, roleId));
//            UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.THREE, NumericalConstants.TWO, ip, tokenUser);
//            setUserOperateContent(true, false, userOperateLog, null, oldRole.getRoleName(), null,
//                    roleTypeMap.get(oldRole.getRoleType()), null, oldRole.getRoleSign(), null, oldMenuName);
//            userOperateLogMapper.insert(userOperateLog);
        }
        return delete;
    }

    /**
     * 角色集合
     *
     * @return
     */
    @Override
    public JsonResult<List<RoleVO>> rolePageList(PageDTO dto, Integer roleType) {
        IPage<Role> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        if (roleType != null) {
            queryWrapper.lambda().eq(Role::getRoleType, roleType);
        }
        //超级管理员的角色拥有所有权限不返回
        queryWrapper.lambda().ne(Role::getRoleSign, "SUPER_ADMIN");
        queryWrapper.lambda().orderByDesc(Role::getCreateTime);
        IPage<Role> iPage = roleMapper.selectPage(page, queryWrapper);
        List<Role> records = iPage.getRecords();
        List<RoleVO> voList = new ArrayList<>();
        records.stream().forEach(item -> {
            RoleVO vo = new RoleVO();
            BeanUtils.copyProperties(item, vo);
            Long roleId = item.getRoleId();
            List<RoleMenu> roleMenus = roleMenuMapper.selectList(Wrappers.<RoleMenu>lambdaQuery().eq(RoleMenu::getRoleId, roleId));
            if (!roleMenus.isEmpty()) {
                List<Integer> menuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
                List<Menu> menus = menuMapper.selectList(Wrappers.<Menu>lambdaQuery().in(Menu::getMenuId, menuIds));
                vo.setMenuTreeVOS(menuService.structureErection(menus));
            }
            voList.add(vo);
        });
        return JsonResult.success(voList, iPage.getTotal());
    }
}
